#include <sstream>
#include "MotorJuegoServicio.h"
#include "MotorJuegoServicioConstantes.h"
#include "ProtocoloConstantes.h"

using namespace std;
using namespace TP::Servicios;
using namespace TP::Comunicacion;

#define COMANDO_INVALIDO 0
#define JUGADOR_INVALIDO 1
#define POSICION_INVALIDA 2

MotorJuegoServicio::MotorJuegoServicio() { }

MotorJuegoServicio::~MotorJuegoServicio() { }

void MotorJuegoServicio::iniciar() { }

void MotorJuegoServicio::finalizar() { }

void MotorJuegoServicio::mensajeEntranteManejador(IMensajero* pMensajero,
		const string& pMensaje) {
	try {
		vector<string> comando;
		this->hidratarMensaje(pMensaje, comando);
		if (MOTOR_JUEGO == comando[0]) {
			if (GET_PARTIDA == comando [1])
				this->getPartida(pMensajero, comando);

			if (ATACAR == comando[1])
				this->atacar(pMensajero, comando);
		}

	}
	catch (Excepcion& pEx) {
		cerr << pEx.what() << endl;
	}
}

void MotorJuegoServicio::getPartida(IMensajero* pMensajero,
		vector<string>& pComando) {
	_mutex.lock();
	Jugador* jugador = NULL;
	try {
		// Buscar la partida correspondiente al Jugador que invoca la solicitud.
		jugador = Jugador::crearDeXML(pComando[2]);
		string partida = this->_motor->getPartidaPorJugadorAString(jugador);
		if (partida.length() > 0)
			this->notificar(pMensajero, partida);
		else
			this->notificar(pMensajero, NULO);
	}
	catch (Excepcion& pEx) {
		this->notificarError(pMensajero, pEx.what());
		cerr << pEx.what() << endl;
	}
	_mutex.unlock();
	// ...me aseguro que e liberen los recursos en caso de haber.
	if (jugador) delete jugador;
}

void MotorJuegoServicio::setMotorJuego(MotorJuego* pMotor) {
	if (pMotor)
		this->_motor = pMotor;
}

void MotorJuegoServicio::atacar(IMensajero* pMensajero,
		vector<string>& pComando) {
	// 0: MOTOR_JUEGO, 1: atacar, 2: jugador, 3: nombrepartida, 4: posicion;
	Jugador* jugador = NULL;
	Posicion* posicion = NULL;
	_mutex.lock();
	try {
		jugador = Jugador::crearDeXML(pComando[2]);
		if (!jugador) throw JUGADOR_INVALIDO;

		posicion = Posicion::crearDeXML(pComando[4]);
		if (!posicion) throw POSICION_INVALIDA;

		this->_motor->atacar(jugador, pComando[3], posicion);
		this->notificar(pMensajero, "Ataque exitoso.");
	}
	catch (int pEx) {
		switch (pEx) {
			case JUGADOR_INVALIDO:
				this->notificarError(pMensajero,
						"No se puede hidratar el jugador.");
				break;

			case POSICION_INVALIDA:
				this->notificarError(pMensajero,
						"No se puede hicratar la posicion.");
				break;
		}
	}
	catch (Excepcion& pEx) {
		this->notificarError(pMensajero, pEx.what());
		cerr << pEx.what() << endl;
	}
	_mutex.unlock();
	if (jugador) delete jugador;
	if (posicion) delete posicion;
}
